// NES 2A03 APU sound chip emulator with simpler interface

// Nes_Snd_Emu 0.1.7. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.

#ifndef SIMPLE_APU_H
#define SIMPLE_APU_H

#include "nes_apu/Blip_Buffer.h"
#include "nes_apu/Nes_Apu.h"
#include <QDataStream>

#define BUFFER_SIZE 2048

class Simple_Apu
{
    friend QDataStream &operator<<(QDataStream &stream, const Simple_Apu &Apu); // 序列化
    friend QDataStream &operator>>(QDataStream &stream, Simple_Apu &Apu);       // 反序列化
public:
	Simple_Apu();
    ~Simple_Apu();

    void reset(); // 读取新卡带后，重置

    // This simpler interface works well for most games. Some benefit from
	// the higher precision of the full Nes_Apu interface, which provides
	// clock-cycle accurate register read/write and IRQ timing functions.

	// Set function for APU to call when it needs to read memory (DMC samples)
    void dmc_reader(int (*callback)(void *user_data, cpu_addr_t), void *user_data = NULL);

    // Set output sample rate
    blargg_err_t sample_rate(long rate);

    // Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
    void write_register(cpu_addr_t, int data);

    // Read from status register at 0x4015
    int read_status();

    // Number of samples in buffer
    long samples_avail() const;

    // Read at most 'count' samples and return number of samples actually read
	typedef blip_sample_t sample_t;
	long read_samples(sample_t* buf, long buf_size);

	// Save/load snapshot of emulation state
	void save_snapshot(apu_snapshot_t* out) const;
	void load_snapshot(apu_snapshot_t const&);

    // End a 1/60 sound frame
    void end_frame();

public:
    blip_sample_t out_buf[BUFFER_SIZE];
    size_t out_count;

private:
	Nes_Apu apu;
	Blip_Buffer buf;
    blip_time_t time;
    blip_time_t frame_length;
    blip_time_t clock() { return time += 4; }
};

#endif
